﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using com.IronOne.BoardPACWinApp.Common;
using com.IronOne.BoardPACWinApp.Helpers;
using com.IronOne.BoardPACWinAppBO.Auth;
using com.IronOne.BoardPACWinAppBO.Settings;
using com.IronOne.BoardPACWinAppService.Auth;
using com.IronOne.BoardPACWinAppService.Init;
using com.IronOne.BoardPACWinAppUtil.Enums;
using com.IronOne.BoardPACWinAppUtil.Security;
using com.IronOne.BoardPACWinAppUtil.Util;

// ReSharper disable All

// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237

namespace com.IronOne.BoardPACWinApp.View.Page
{
    /// <summary>
    ///     A basic page that provides characteristics common to most applications.
    /// </summary>
    public sealed partial class SplashPage
    {
        private IAppSettingsManager _appSettingsManager;
        private IAuthService _authService;
        private IInitService _initService;
        private INavigationService _navigationService;

        public SplashPage()
        {
            InitializeComponent();
            _navigationService = new NavigationService();
            _initService = new InitService();
            _authService = new AuthService();
            _appSettingsManager = new AppSettingsManager();

            Global.IsOnline = true;
            Global.UserForceWentOffline = false;

            var stat = _initService.CreateGeneralDatabase();
            if (!stat)
            {
                throw new Exception("Failed to create general database");
            }
        }

        /// <summary>
        ///     Populates the page with content passed during navigation.  Any saved state is also
        ///     provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="navigationParameter">
        ///     The parameter value passed to
        ///     <see cref="Frame.Navigate(Type, Object)" /> when this page was initially requested.
        /// </param>
        /// <param name="pageState">
        ///     A dictionary of state preserved by this page during an earlier
        ///     session.  This will be null the first time a page is visited.
        /// </param>
        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
        }

        /// <summary>
        ///     Preserves state associated with this page in case the application is suspended or the
        ///     page is discarded from the navigation cache.  Values must conform to the serialization
        ///     requirements of <see cref="SuspensionManager.SessionState" />.
        /// </summary>
        /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
        protected override void SaveState(Dictionary<String, Object> pageState)
        {
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            await CommonFunc();
        }

        private async Task CommonFunc()
        {
            try
            {
                SpRetryPanel.Visibility = Visibility.Collapsed;
                PgrProgress.Visibility = Visibility.Visible;

                var asm = await ManipAppSettingsData();
                if (asm == null)
                {
                    DisplayError("App settings encounter an error");
                    return;
                }

                #region Task.WhenAll

                var resultModels1 = await Task.WhenAll
                    (
                        _authService.GetSettingValueBySettingName(DatabaseType.GeneralDb,
                            ApplicationConstants.GeneralDbSettingNames.CooperateId),
                        _authService.GetSettingValueBySettingName(DatabaseType.GeneralDb,
                            ApplicationConstants.GeneralDbSettingNames.ServerUrl)
                    );

                #endregion

                Global.CooperateId = "1";
                if (resultModels1[0] != null)
                    Global.CooperateId = String.IsNullOrWhiteSpace(resultModels1[0].ToString())
                        ? Global.CooperateId = "1"
                        : Global.CooperateId;

                if (resultModels1[1] != null)
                    Global.ServerUrl = resultModels1[1].ToString();

                var isSvrUp = await NetworkConnectivityManager.ServerUpCheckOnce();
                NetworkConnectivityManager.ServerUpCheck();

                if (!isSvrUp) //Offline
                {
                    var dm = await _authService.GetDeviceAuthStatus();
                    if (dm.DeviceRegistrationStatus == (int) DeviceStatus.Wipeout)
                    {
                        _navigationService.NavigateTo(typeof (WipedOutPage));
                        return;
                    }
                    if (dm.DeviceRegistrationStatus != (int) DeviceStatus.Active)
                    {
                        DisplayError("Connection to the server has been lost");
                        return;
                    }
                    var dateFormat = await _initService.GetDateFormat();
                    Global.DateFormat = dateFormat;
                    _navigationService.NavigateTo(typeof (LoginPage));
                    return;
                }

                //If Online
                var devId = DeviceService.GetAppSpecificHardwareId();
                var rdModel = await _authService.DeviceAuthorizeStatus(devId);

                if (rdModel.IsError)
                {
                    DisplayError(rdModel.ErrorMessage);
                    return;
                }

                var regStatus = Convert.ToInt32(rdModel.Data);
                if (regStatus == (int) DeviceStatus.Rejected)
                    regStatus = (int) DeviceStatus.NotRegisterd;

                await _authService.SetDeviceAuthStatus(new DeviceModel {DeviceRegistrationStatus = regStatus});

                if ((regStatus == (int) DeviceStatus.Pending) || (regStatus == (int) DeviceStatus.NotRegisterd))
                {
                    _navigationService.NavigateTo(typeof (LoginPage));
                    return;
                }
                if (regStatus == (int) DeviceStatus.Deactive)
                {
                    DisplayError("Your device is deactivated");
                    return;
                }
                if (regStatus == (int) DeviceStatus.Wipeout)
                {
                    _navigationService.NavigateTo(typeof (WipedOutPage));
                    return;
                }
                if (regStatus == (int) DeviceStatus.Active)
                {
                    #region Do all the init stuff

                    var dateFormat = await _initService.GetDateFormat();
                    Global.DateFormat = dateFormat;

                    asm = await _initService.InitDevice(asm);
                    if (asm.IsError)
                    {
                        DisplayError(asm.ErrorMessage);
                        return;
                    }

                    var minWebVersion = int.Parse(asm.MinWebVersion.Replace(".", "").Trim());
                    var currentWebVersion = int.Parse(asm.CurrentWebVersion.Replace(".", "").Trim());
                    //asm.CurrentWebVersion
                    if (!(currentWebVersion >= minWebVersion))
                    {
                        DisplayError(
                            "You are connecting to a older version of the BoardPAC web. Please contact your administrator.\n" +
                            "Current web version: " + asm.CurrentWebVersion + "\nMinimum supported web version: " +
                            asm.MinWebVersion);
                        return;
                    }

                    var rVal = await _initService.WriteAppSettingsToDb(asm);
                    if (!rVal)
                    {
                        DisplayError("App settings encounter an error");
                        return;
                    }

                    _navigationService.NavigateTo(typeof (LoginPage));

                    #endregion
                }
            }
            catch (Exception)
            {
                DisplayError("Initialization failed");
            }
        }

        private async Task<AppSettingModel> ManipAppSettingsData()
        {
            try
            {
                var dbSettings = await _initService.ReadAppSettingsFromDb();

                //Settings not available in DB (New DB)
                if (dbSettings == null)
                {
                    var asm = await _appSettingsManager.ReadAppSettingsFromXmlFile();
                    asm = UpdateRoamingOrLocalSettings(asm);
                    await _initService.WriteAppSettingsToDb(asm);
                    return asm;
                }

                //Settings available in DB

                //Write DateFormats and SyncFreqs from file to db, otherwise file updates about these items
                //will never reflect on DB unless de deleted and recreated again.
                var asMod = await _appSettingsManager.ReadDateFormatsNSyncFreqsFromXmlFile();
                await _initService.WriteDateFormatsNSyncFreqsToDb(asMod);

                dbSettings.MinWebVersion = asMod.MinWebVersion;
                dbSettings.DateFormats = asMod.DateFormats;
                dbSettings.SyncFrequencies = asMod.SyncFrequencies;
                dbSettings = UpdateRoamingOrLocalSettings(dbSettings);
                return dbSettings;
            }
            catch (Exception)
            {
            }
            return null;
        }

        private AppSettingModel UpdateRoamingOrLocalSettings(AppSettingModel asm)
        {
            try
            {
                if (asm.SyncSettings) //Roaming
                {
                    var roamData = _appSettingsManager.ReadAppSettingsFromRoamingSettings();
                    if (roamData != null)
                    {
                        asm.DateFormats = roamData.DateFormats;
                        asm.DateFormatSelected = roamData.DateFormatSelected;
                        asm.ServerUrl = roamData.ServerUrl;
                        asm.SyncFrequencies = roamData.SyncFrequencies;
                        asm.SyncFrequencySelected = roamData.SyncFrequencySelected;
                    }
                }
            }
            catch (Exception)
            {
            }
            return asm;
        }

        private void DisplayError(string errMgs)
        {
            LblErrorMsg.Text = errMgs;
            SpRetryPanel.Visibility = Visibility.Visible;
            PgrProgress.Visibility = Visibility.Collapsed;
        }

        private async void btn_Retry_Click(object sender, RoutedEventArgs e)
        {
            await CommonFunc();
        }

        private void pageRoot_Unloaded(object sender, RoutedEventArgs e)
        {
            _navigationService = null;
            _initService = null;
            _authService = null;
            _appSettingsManager = null;
        }
    }
}